package com.chengcang.api.common.utils;


import com.chengcang.api.modules.sys.entity.DictData;
import com.chengcang.common.redis.RedisUtils;
import com.chengcang.common.utils.JsonUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author hrh
 * @version v1.2
 * @ClassName DicTransLateUtil.java
 * @Description 字典转换(字典字段的属性名要与字典表中DATA_KEY_TYPE的相同 ， 按驼峰式转换)
 * @createTime 2021年06月10日 19:44:00
 */
@Slf4j
@Component
public class DicTransLateUtil {

    private static RedisUtils redisUtils;

    public static final String DIC_TYPE_KEY = "sys:dict:data";

    @Autowired
    public void setRedisUtils(RedisUtils redisUtils) {
        DicTransLateUtil.redisUtils = redisUtils;
    }


    public static <T> T translate(Object obj, boolean addStr, Class<T> clazz) throws Exception {
        Map<String, Object> map = new ObjectMapper().convertValue(obj, Map.class);
        translate(map, addStr);
        return (T) mapToObject(map, clazz);
    }


    private static Object mapToObject(Map<String, Object> map, Class<?> clazz) {
        if (map == null) {
            return null;
        }
        return JsonUtils.parseObject(JsonUtils.toJsonString(map), clazz);
    }


    /**
     * 翻译字典值
     *
     * @author panlei
     * @date 2021/6/11 14:11
     **/
    private static void translate(Map<String, Object> data, boolean addStr) {
        if (data == null || data.size() <= 0) {
            return;
        }
        Set<String> keySets = new HashSet<>(data.size());
        keySets.addAll(data.keySet());
        for (String key : keySets) {
            Object value = data.get(key);
            // value == null 的情况下如果需要翻译 还需要翻译成null返回
            if (value != null && StringUtils.isBlank(value.toString())) {
                continue;
            }
            if (value instanceof Map) {
                translate((Map<String, Object>) value, addStr);
                continue;
            }
            if (value instanceof List) {
                List<Object> list = translateList((List<Object>) value, key, addStr);
                String listStr = StringUtils.join(list, ",");
                if (addStr) {
                    data.put(key + "Name", listStr);
                    continue;
                }
                data.put(key, list);
                continue;
            }
            Map<String, String> keyDataMap = getDataByField(key);
            if (keyDataMap.size() < 0) {
                continue;
            }
            if (value == null) {
                continue;
            }
            String keyValue = keyDataMap.get(value.toString());
            if (StringUtils.isBlank(keyValue)) {
                continue;
            }
            if (addStr) {
                data.put(key + "Name", keyValue);
            } else {
                data.put(key, keyValue);
            }
        }
    }

    private static List<Object> translateList(List<Object> list, String key, boolean addStr) {
        if (list == null || list.size() == 0) {
            return list;
        }
        List<Object> newList = new ArrayList<>(list.size());
        for (Object o : list) {
            if (o instanceof Map) {
                translate((Map<String, Object>) o, addStr);
                newList.add(o);
                continue;
            }
            if (o instanceof List) {
                o = translateList((List<Object>) o, "", addStr);
                newList.add(o);
                continue;
            }
            if (StringUtils.isBlank(key)) {
                continue;
            }
            Map<String, String> keyDataMap = getDataByField(key);
            if (keyDataMap.size() < 0) {
                continue;
            }
            String keyValue = keyDataMap.get(o.toString());
            if (StringUtils.isBlank(keyValue)) {
                continue;
            }
            newList.add(keyValue);
        }
        return newList;
    }


    public static Map<String, String> getDataByField(String fieldName) {
        Map<String, String> resultMap = new HashMap<>(1);
        //查询单个数据字典key
        if (StringUtils.isNotBlank(fieldName)) {
            Object fieldObj = redisUtils.hGet(DIC_TYPE_KEY, humpToLine(fieldName));
            if (fieldObj != null) {
                List<DictData> list = (List<DictData>) fieldObj;
                for (DictData dictData : list) {
                    resultMap.put(dictData.getDictValue(), dictData.getDictLabel());
                }
                return resultMap;
            }
        }
        //resultMap根据dataSort进行排序
        return resultMap;
    }

    private static Pattern linePattern = Pattern.compile("_(\\w)");

    /**
     * 下划线转驼峰
     */
    private static String lineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    /**
     * 驼峰转下划线,效率比上面高
     */
    public static String humpToLine(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

}
